<template>
  <div class="custom-upload">
    <input
      :id="id"
      type="file"
      style="display: none"
      name="single"
      @change="onChange"
    />
    <!-- accept="image/*" -->
    <div @click="handleOpenFile">
      <slot>
        <div class="img_btn">
          <el-button size="small" type="primary" :loading="loading">
            <div class="fa fa-plus">
              <el-row
                ><el-col style="margin-top: 10px">上传图像</el-col></el-row
              >
            </div>
          </el-button>
        </div>
      </slot>
    </div>

    <div v-if="tips" class="tips clear-margin-top">{{ tips }}</div>
  </div>
</template>

<script>
// 上传文件组件
import {
  minioAddress,
  minioPort,
  isAppropriateResolution,
  isAppRatio,
  isImageFile,
  isMaxFileSize,
  minioServer,
  minioBucket,
  setMinioPolicy,
} from "./uploadImg";

// let Minio = require("minio");
// let stream = require("stream");
import { Message } from "element-ui";
export default {
  name: "UploadImg",
  props: {
    // 最大上传文件的大小 单位（MB）
    maxFileSize: {
      type: Number,
      default: 2,
    },
    // 提示内容
    tips: {
      type: String,
    },
    // 图片文件分辨率的宽度
    width: {
      type: Number,
      width: 460,
    },
    // 图片文件分辨率的高度
    height: {
      type: Number,
      default: 300,
    },
    // 是否限制分辨率
    isResolution: {
      type: Boolean,
      default: false,
    },
    // 是否限制比列
    isRatio: {
      type: Boolean,
      default: false,
    },
    // 比列 ag: 1:1 时给 [1,1]
    ratio: {
      type: Array,
    },
    // 外部传入租户
    tenant2: {
      type: String,
      default: "",
    },
    // 是否携带租户
    isTenant: {
      type: Boolean,
      default: true,
    },
    // 自定义拼接的url
    customKey: {
      type: String,
      default: "",
    },
    isAsycn: {
      type: Boolean,
      default: false,
    },
  },
  data() {
    return {
      minioClient: null,
      id: "upload-input-" + +new Date(),
      loading: false,
      ImageUrl: "",
    };
  },
  computed: {
    urlPrefix() {
      const customKey = this.customKey ? `/${this.customKey}/` : "/";
      const url = this.isTenant
        ? `/${process.env.VUE_APP_MINIO_bucket}/${this.tenant}/${this.$route.meta.iotName}${customKey}`
        : `/${process.env.VUE_APP_MINIO_bucket}/${this.$route.meta.iotName}`;
      return url;
    },
    newUrl() {
      const customKey = this.customKey ? `${this.customKey}/` : "";
      const newUrl = this.isTenant
        ? `${this.tenant}/${this.$route.meta.iotName}/${customKey}`
        : `${this.$route.meta.iotName}/`;
      return newUrl;
    },
    tenant() {
      const tenant = this.tenant2
        ? this.tenant2
        : this.$store.state.user.tenant.token;
      return this.isTenant ? tenant : "";
    },
  },
  mounted() {
    this.minioClient = new this.$Minio.Client(minioServer);
  },
  methods: {
    // 打开文件
    handleOpenFile() {
      const input = document.getElementById(this.id);
      // 解决同一个文件不能监听的问题
      input.addEventListener(
        "click",
        function () {
          this.value = "";
        },
        false
      );
      // 点击input
      input.click();
    },

    // 选择好文件
    async onChange($event) {
      const that = this;
      // this.loading = true;
      const file = $event.target.files[0];
      file.path = $event.target.value;
      if (!file) {
        this.loading = false;
        return Message.error("选择图片失败");
      }
      if (this.isAsycn) {
        let reader = new FileReader();
        reader.readAsDataURL(file);
        reader.onloadend = function (e) {
          const dataurl = e.target.result;
          that.$emit("subUploadSucceedAsync", dataurl, file);
        };
      } else {
        // 限制为图片文件
        // if (!isImageFile(file)) {
        //   this.loading = false;
        //   return;
        // }

        // 限制文件上传大小
        // if (!isMaxFileSize(file, this.maxFileSize)) {
        //   this.loading = false;
        //   return;
        // }

        try {
          // 限制分辨率
          // if (this.width !== 0 && this.height !== 0 && this.isResolution) {
          //   await isAppropriateResolution(file, {
          //     width: this.width,
          //     height: this.height
          //   })
          // }

          // 限制比列
          // if (this.isRatio && this.ratio && this.ratio.length === 2) {
          //   await isAppRatio(file, this.ratio)
          // }
          // 开始上传
          this.uploadFiles(file);
        } catch (error) {
          Message.error(error.message || "上传失败");
          console.log(error);
          this.loading = false;
        }
      }
    },

    // 自定义上传
    async uploadFiles(file) {
      let that = this;
      console.log("this.minioClient :>> ", this.minioClient);
      return new Promise(async (resolve, reject) => {
        try {
          //判断储存桶是否存在
          await this.minioClient.bucketExists(
            minioBucket,
            function (err, exists) {
              if (err) {
                that.$msg({
                  type: "warning",
                  message: err,
                });
                return;
              }
              if (exists) {
                that.putObject(file).then((res) => {
                  resolve(res);
                });
              } else {
                //不存在 创建存储桶
                that.minioClient.makeBucket(
                  minioBucket,
                  "cn-north-1",
                  function (err) {
                    if (err) {
                      that.$msg({
                        type: "warning",
                        message: "文件服务器创建文件柜失败!",
                      });
                    } else {
                      //设置访问策略
                      var policy = setMinioPolicy(minioBucket, "readwrite");
                      that.minioClient.setBucketPolicy(
                        minioBucket,
                        policy,
                        function (err) {
                          if (err) {
                            that.$msg({
                              type: "warning",
                              message: "文件柜添加访问策略失败!",
                            });
                            reject('文件柜添加访问策略失败!"');
                          } else {
                            that.putObject(file).then((res) => {
                              resolve(res);
                            });
                          }
                        }
                      );
                    }
                  }
                );
              }
            }
          );
          this.loading = false;
        } catch (error) {
          this.loading = false;
          console.log(error);
          that.$msg({
            type: "error",
            message: error.message || "上传失败",
          });
        }
      });
    },
    putObject(file) {
      return new Promise((resolve, reject) => {
        let that = this;
        let reader = new FileReader();
        reader.readAsDataURL(file);
        reader.onloadend = function (e) {
          console.log("exxxxxxxx :>> ", e);
          const dataurl = e.target.result;
          //base64转blob
          const blob = that.toBlob(dataurl);
          //blob转arrayBuffer
          let reader2 = new FileReader();
          reader2.readAsArrayBuffer(blob);

          reader2.onload = function (ex) {
            //定义流
            let bufferStream = new that.$stream.PassThrough();
            //将buffer写入
            bufferStream.end(new Buffer(ex.target.result));
            //上传
            //参数
            let metadata = {
              "content-type": file.type,
              "content-length": file.size,
            };
            that.minioClient.putObject(
              minioBucket,
              `${that.newUrl}${file.name}`,
              bufferStream,
              file.size,
              metadata,
              function (err, etag) {
                if (err) {
                  that.$msg({
                    type: "warning",
                    message: "上传失败!",
                  });
                  console.log("上传失败", err);
                } else {
                  that.$msg({
                    type: "success",
                    message: "上传成功!",
                  });
                  // /iot/0001/area/default_area.jpg
                  var imgUrl = `${that.urlPrefix}${file.name}`;
                  that.$emit("subUploadSucceed", imgUrl);
                  resolve(imgUrl);
                }
              }
            );
          };
        };
      });
    },
    toBlob(base64Data) {
      let byteString = base64Data;
      if (base64Data.split(",")[0].indexOf("base64") >= 0) {
        byteString = atob(base64Data.split(",")[1]); // base64 解码
      } else {
        byteString = unescape(base64Data.split(",")[1]);
      }
      // 获取文件类型
      let mimeString = base64Data.split(";")[0].split(":")[1]; // mime类型

      // ArrayBuffer 对象用来表示通用的、固定长度的原始二进制数据缓冲区
      // let arrayBuffer = new ArrayBuffer(byteString.length) // 创建缓冲数组
      // let uintArr = new Uint8Array(arrayBuffer) // 创建视图

      let uintArr = new Uint8Array(byteString.length); // 创建视图

      for (let i = 0; i < byteString.length; i++) {
        uintArr[i] = byteString.charCodeAt(i);
      }
      // 生成blob
      const blob = new Blob([uintArr], {
        type: mimeString,
      });
      // 使用 Blob 创建一个指向类型化数组的URL, URL.createObjectURL是new Blob文件的方法,可以生成一个普通的url,可以直接使用,比如用在img.src上
      return blob;
    },
  },
};
</script>

<style lang="scss"  scoped >
.custom-upload {
  .tips {
    margin-top: 10px;
    color: red;
    font-size: 12px;
  }
  .clear-margin-top {
    margin-top: 0;
  }
}
.img_btn {
  .el-button--primary {
    width: 104px;
    height: 104px;
    background: rgba(0, 0, 0, 0.04);
    border: 1px solid rgba(0, 0, 0, 0.14901960784313725);
    opacity: 1;
    border-radius: 2px;
    color: #000000;
    background-color: #e8ebec;
    border-color: #e8ebec;
  }
  .custom-upload .el-button--primary {
    /* width: 100%; */
    height: 104px;
    background: rgba(0, 0, 0, 0.04);
    border: 1px solid rgba(0, 0, 0, 0.14901960784313725);
    opacity: 1;
    border-radius: 2px;
  }
  .fa /deep/.fa-plus {
    display: inline-block;
    font: normal normal normal 0.84848vw/1 FontAwesome;
    font-size: 16px;
    text-rendering: auto;
    -webkit-font-smoothing: antialiased;
  }
  .fa-plus:before {
    font-size: 24px;
  }
}
</style>
